package concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 优先级
 *
 * 2018年 09月 22日 星期六
 * @author fireway
 */
public class SimplePriorities implements Runnable {
    private int mCountDown = 5;

    // No optimization
    // 变量mVD是volatile修饰的，以努力确保不进行任何编译器优化
    private volatile double mVD;

    private int mPriority;

    public SimplePriorities(int priority) {
        mPriority = priority;
    }

    // toString()方法被覆盖，以便使用Thread.toString()方法打印
    // 线程的名称、线程的优先级以及线程所属的"线程组"。
    public String toString() {
        // 注意，你可以在一个任务内部，通过调用Thread.currentThread()
        // 来获得对驱动该任务的Thread对象的引用。
        return Thread.currentThread() + ": " + mCountDown;
    }

    /**
     * An expensive, interruptable operation:
     * 执行XXX次开销相当大的浮点运算, 开平方运算，包括double类型的加法与除法
     * 有了这些运算就能看到优先级为MAX_PRIORITY的线程被线程调度器
     * 优先选择
     */
    private void longRunningOperator() {
        for (int k = 0; k < 100; k++) {
            for (int j = 0; j < 100; j++) {
                for(int i = 1; i < 10000; i++) {
                    mVD = (Math.PI + Math.E) / (double)i;
                    mVD = mVD * mVD * mVD + (Math.PI + Math.E);
                    mVD = Math.sqrt(mVD);
                    mVD = Math.sqrt(mVD);
                    mVD = Math.sqrt(mVD);
                    mVD = Math.sqrt(mVD);
                    if(i % 1000 == 0) {
                        Thread.yield();
                    }
                }
            }
        }
    }

    @Override
    public void run() {
        Thread.currentThread().setPriority(mPriority);
        while(true) {
            long startTime = System.nanoTime();
            longRunningOperator();
            long duration = System.nanoTime() - startTime;

            System.out.println(this + ", duration = " + duration);
            if(--mCountDown == 0) {
                return;
            }
        }
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for(int i = 0; i < 5; i++) {
            exec.execute(new SimplePriorities(Thread.MIN_PRIORITY));
        }
        // 最后一个线程的优先级最高，其余所有线程的优先级被设为最低。
        exec.execute(new SimplePriorities(Thread.MAX_PRIORITY));
        exec.shutdown();
    }
}
